package com.stox.manager;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.Lifecycle;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.stox.model.DataStream;
import com.stox.model.entity.ExchangeEntity;
import com.stox.model.entity.ExchangeDownloadMetaData;
import com.stox.provider.DataProvider;
import com.stox.util.Constant;

@Component
public class DownloadManager implements DisposableBean, Lifecycle{
	private static final Logger logger = LoggerFactory.getLogger(DownloadManager.class);
	
	@Autowired
	private DataProvider dataProvider;

	@Autowired
	private BarManager barManager;

	@Autowired
	private ExchangeManager exchangeManager;
	
	@Autowired
	private ExchangeDownloadMetaDataManager exchangeDownloadMetaDataManager;

	private boolean cancelRequested;
	private boolean running;
	
	public void cancel(){
		cancelRequested = true;
		while(running){
			Thread.yield();
		}
	}
	
	@Override
	public void destroy() throws Exception {
		stop();
	}
	
	@Override
	public boolean isRunning() {
		return running;
	}
	
	@Override
	public void start() {
		
	}
	
	@Override
	public void stop() {
		cancel();
	}
	
	@Scheduled(fixedDelay=60000)
	public void download() {
		List<ExchangeEntity> exchanges = exchangeManager.findAll();
		if (exchanges != null && !exchanges.isEmpty()) {
			for (ExchangeEntity exchange : exchanges) {
				bredthDownload(exchange);
				barManager.flush();
				if(cancelRequested) return;
			}
		}
	}
	
	public void bredthDownload(final ExchangeEntity exchange) {
		if(cancelRequested) return;
		final Calendar calendar = Calendar.getInstance();
		ExchangeDownloadMetaData exchangeDownloadMetaData = 
				exchangeDownloadMetaDataManager.findByExchangeCode(exchange.getCode());
		if(null == exchangeDownloadMetaData){
			exchangeDownloadMetaData = new ExchangeDownloadMetaData();
			exchangeDownloadMetaData.setExchange(exchange);
			calendar.add(Calendar.YEAR, -5);
			exchangeDownloadMetaData.setLastDownloadDate(calendar.getTime());
			exchangeDownloadMetaDataManager.save(exchangeDownloadMetaData);
		}
		calendar.setTime(exchangeDownloadMetaData.getLastDownloadDate());
		Date endDate = new Date();
		while (!calendar.getTime().after(endDate) && !cancelRequested) {
			if(!cancelRequested){
				running = true;
			}
			try {
				calendar.add(Calendar.DATE, 1);
				if (isWeekend(calendar)) continue;
				long start = System.currentTimeMillis();
				logger.info("Download : Started - date : "+Constant.dateFormat.format(calendar.getTime()));
				DataStream dataStream = dataProvider.get(exchange,calendar.getTime());
				if(cancelRequested) return;
				if (dataStream != null && dataStream.getBarList() != null && !dataStream.getBarList().isEmpty()) {
					barManager.save(dataStream.getBarList());
					exchangeDownloadMetaData.setLastDownloadDate(calendar.getTime());
					exchangeDownloadMetaDataManager.save(exchangeDownloadMetaData);
					logger.info(",Completed - Bars downloaded : "+dataStream.getBarList().size()+", Time taken : "+(System.currentTimeMillis()-start)/1000);
				}
			} catch (Throwable t) {
				t.printStackTrace();
			}finally{
				running = false;
			}
		}
	}
	
	public boolean isWeekend(Calendar calendar){
		return Calendar.SUNDAY == calendar.get(Calendar.DAY_OF_WEEK) || 
				Calendar.SATURDAY == calendar.get(Calendar.DAY_OF_WEEK);
	}
	
}
